package ch.ethz.inf.shop.model.simpleDatabase.operators.tests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import ch.ethz.inf.shop.model.Brand;
import ch.ethz.inf.shop.model.Category;
import ch.ethz.inf.shop.model.Comment;
import ch.ethz.inf.shop.model.DatastoreInterfaceSimpleDatabase;
import ch.ethz.inf.shop.model.Product;
import ch.ethz.inf.shop.model.Recipe;
import ch.ethz.inf.shop.model.RegisteredUser;
import ch.ethz.inf.shop.model.ShoppingCartLine;
import ch.ethz.inf.shop.model.simpleDatabase.Tuple;

/**
 * This class can contain all the test, to test
 * DatastoreInterfaceSimpleDatabase. It is easier to run the tests, than always
 * clicking trough the WebInterface...
 * 
 * @author rop
 * 
 */
public class TestDBInterface {

	private DatastoreInterfaceSimpleDatabase dbInterface;
	private static final Product HAIFISCH = new Product(5, "Haifisch Wildfang", new BigDecimal("999.99"), 150000, "Internationales Seegewaesser", new Category(
			"Fisch", 1), new Brand("Nestle", 1), 0);

	private static final Product PAPRIKA = new Product(12, "Paprika", new BigDecimal("0.70"), 30, "Niederlande", new Category("Gewuerze", 5), new Brand(
			"Migros", 2), 2);

	private static final Category GEWUERZE = new Category("Gewuerze", 5);
	private static final Category FISH = new Category("Fisch", 1);

	private static final Brand NESTLE = new Brand("Nestle", 1);
	private static final Brand MIGROS = new Brand("Migros", 2);

	private static final RegisteredUser PHILIPP = new RegisteredUser("rop", "rop", "philipp.rohr@gmail.com", 1);
	private static final RegisteredUser PATRIC = new RegisteredUser("patric", "patric", "patric.rousselot@gmail.com", 2);

	private static Recipe HAIFISCH_FLOSSEN_SUPPE;
	private static Recipe RUEEBLI_THUN_AUFLAUF;
	static {
		try {
			HAIFISCH_FLOSSEN_SUPPE = new Recipe(
					5,
					"Haifischflossensuppe",
					Tuple.HOUR_MINUTE_SECOND_FORMAT.parse("02:20:00"),
					"1. Haifischflosse vom Haifisch abtrennen. 2. Rest des Haifischs an die Katze verfuettern. 3. Haifischflosse puerieren. 4. Bouillon dazugeben. 5. Aufkochen und auf kleiner Flamme koecheln lassen bis es nicht mehr fischelt.",
					new BigDecimal("1002.39"));

			RUEEBLI_THUN_AUFLAUF = new Recipe(1, "Rueebli-Thun-Auflauf", Tuple.HOUR_MINUTE_SECOND_FORMAT.parse("00:20:00"),
					"1. Rueebli in Scheiben schneiden. 2. Thun aus Buechse kratzen, 3. alles mixen, 4. In Ofen bei 400 Grad", new BigDecimal("27.00"));
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Before
	public void setup() {
		dbInterface = new DatastoreInterfaceSimpleDatabase(AllTests.ROOT_DIRECTORY);
	}

	@Test
	public void TestGetProductById() {
		Product p1 = dbInterface.getProductById(5);
		assertEquals(HAIFISCH, p1);
	}

	@Test
	public void TestGetAllProducts() {
		assertEquals(12, dbInterface.getAllProducts().size());
	}

	@Test
	public void TestGetProductByName() {
		List<Product> products = dbInterface.getProductsByName("Haifisch");
		assertEquals(1, products.size());
		assertEquals(HAIFISCH, products.get(0));

		products = dbInterface.getProductsByName("Paprika");
		assertEquals(1, products.size());
		assertEquals(PAPRIKA, products.get(0));
	}

	@Test
	public void TestGetProductByCategory() {
		List<Product> products = dbInterface.getProductsByCategory(GEWUERZE);
		assertEquals(3, products.size());
		assertEquals(PAPRIKA, products.get(2));

		products = dbInterface.getProductsByCategory(FISH);
		assertEquals(3, products.size());
		assertEquals(HAIFISCH, products.get(1));
	}

	@Test
	public void TestGetProductByBrand() {
		List<Product> products = dbInterface.getProductsByBrand(MIGROS);
		assertEquals(8, products.size());
		assertEquals(PAPRIKA, products.get(7));

		products = dbInterface.getProductsByBrand(NESTLE);
		assertEquals(4, products.size());
		assertEquals(HAIFISCH, products.get(2));
	}

	@Test
	public void TestGetAllCategories() {
		List<Category> categories = dbInterface.getAllCategories();
		assertEquals(5, categories.size());
		assertEquals(GEWUERZE, categories.get(4));
		assertEquals(FISH, categories.get(0));

	}

	@Test
	public void TestGetAllBrands() {
		List<Brand> brands = dbInterface.getAllBrands();
		assertEquals(2, brands.size());
		assertEquals(NESTLE, brands.get(0));
		assertEquals(MIGROS, brands.get(1));

	}

	@Test
	public void TestGetProductsByBrandName() {
		List<Product> products = dbInterface.getProductsByBrandName("Nestle");
		assertEquals(4, products.size());
		assertEquals(HAIFISCH, products.get(2));

		products = dbInterface.getProductsByBrandName("Migros");
		assertEquals(8, products.size());
		assertEquals(PAPRIKA, products.get(7));

	}

	@Test
	public void TestGetProductsByCategoryName() {
		List<Product> products = dbInterface.getProductsByCategoryName("Gewuerze");
		assertEquals(3, products.size());
		assertEquals(PAPRIKA, products.get(2));

		products = dbInterface.getProductsByCategoryName("Fisch");
		assertEquals(3, products.size());
		assertEquals(HAIFISCH, products.get(1));

	}

	@Test
	public void TestGetProductsByPopularity() {
		List<Product> products = dbInterface.getProductsByPopularity();
		assertEquals(12, products.size());
		assertEquals(PAPRIKA, products.get(0));
		assertEquals(2, products.get(0).getLikeCount());

		assertEquals(1, products.get(1).getLikeCount());
		assertEquals(1, products.get(2).getLikeCount());
		assertEquals(1, products.get(3).getLikeCount());
		assertEquals(0, products.get(4).getLikeCount());
		assertEquals(0, products.get(5).getLikeCount());
		assertEquals(0, products.get(6).getLikeCount());
		assertEquals(0, products.get(7).getLikeCount());
		assertEquals(0, products.get(8).getLikeCount());
		assertEquals(0, products.get(9).getLikeCount());
		assertEquals(0, products.get(10).getLikeCount());
		assertEquals(0, products.get(11).getLikeCount());

	}

	@Test
	public void TestGetCommentsByProduct() {
		List<Comment> comments = dbInterface
				.getCommentsByProduct(new Product(1, "", new BigDecimal(0), 0, "", new Category("asdf", 0), new Brand("asdf", 1), 0));

		assertEquals(1, comments.size());
		assertEquals("Wie sehr ich diesen Thun doch mag! Vor allem den leckeren Delfin darin!", comments.get(0).getText());

		comments = dbInterface.getCommentsByProduct(PAPRIKA);

		assertEquals(2, comments.size());

	}

	@Test
	public void TestGetUserDetailsFor() {
		assertEquals(PHILIPP, dbInterface.getUserDetailsFor("rop", "rop"));
		assertEquals(PATRIC, dbInterface.getUserDetailsFor("patric", "patric"));

		assertNull(dbInterface.getUserDetailsFor("foo", "bar"));
	}

	@Test
	public void TestGetRecipes() {
		List<Recipe> recipes = dbInterface.getRecipes("price");

		assertEquals(7, recipes.size());
		assertEquals(HAIFISCH_FLOSSEN_SUPPE, recipes.get(0));
		assertEquals(RUEEBLI_THUN_AUFLAUF, recipes.get(1));

		recipes = dbInterface.getRecipes("name");
		assertEquals(7, recipes.size());
		assertEquals(HAIFISCH_FLOSSEN_SUPPE, recipes.get(1));
		assertEquals(RUEEBLI_THUN_AUFLAUF, recipes.get(6));
	}

	@Test
	public void TestGetRecipeById() {
		assertEquals(HAIFISCH_FLOSSEN_SUPPE, dbInterface.getRecipeById(HAIFISCH_FLOSSEN_SUPPE.getRecipeId()));
		assertEquals(RUEEBLI_THUN_AUFLAUF, dbInterface.getRecipeById(RUEEBLI_THUN_AUFLAUF.getRecipeId()));
	}

	@Test
	public void TestGetShoppingCartLinesForUser() {
		List<ShoppingCartLine> lines = dbInterface.getShoppingCartLinesForUser(PATRIC);
		assertEquals(2, lines.size());
	}

	@Test
	public void TestGetShoppingCartPriceForUser() {
		assertEquals(new BigDecimal("51.80"), dbInterface.getShoppingCartPriceForUser(PATRIC));
	}
}
